#include <iostream>
#include <functional>
#include <memory>

#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "Calcuate.hpp"

using namespace Space_Protocol;
using call_t = std::function<Response(const Request &)>;

void Usage(const std::string &tip)
{
    std::cout << "Please Use:\n\t" << tip << " local_port\n"
              << std::endl;
}

class CallServe
{
public:
    CallServe(call_t call) : _call(call) {}
    void server(sock_ptr sp, InetAddr client)
    {
        LOG(DEBUG, "tcpserver get a new link,this is:%s:%d\n", client.Ip().c_str(), client.Port());

        std::string clinetmessage = "[" + client.Ip() + ":" + std::to_string(client.Port()) + "]#";
        std::string inbuffer;
        sleep(5);
        while (1)
        {
            Request req;
            // 1.要保证接收的字符串里面有一个完整的请求
            int n = sp->Recv(&inbuffer);
            if (n < 0)
            {
                LOG(DEBUG, "client%s quit\n", client.Ip().c_str());
                break;
            }
            std::string package;
          
            while (1)
            {
                usleep(99999);
                std::cout << "----------------------------------------------------"<<std::endl;

                std::cout << "inbuffer\n" << inbuffer << std::endl;
                // 2.分析数据:去掉报头
                package = Decode(inbuffer);
                if (package.empty())
                    break;
                std::cout << "req string:\n"
                          << package;
                ////////////////////////////////////
                // 3.反序列化
                req.Re_Serialize(package);

                // 4.业务处理

                Response rsp = _call(req);

                // 5.对响应序列化
                std::string send_str;
                rsp.Serialize(&send_str);
                std::cout << "resp Serialize:\n"
                          << send_str;
                // 6.加报头
                send_str = Encode(send_str);
                std::cout << "resp Encode:\n"
                          << send_str;

                // 7.发送
                sp->Send(send_str);
            }
        }
    }

private:
    call_t _call;
};
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERROR);
    }

    EnableScreen();

    uint16_t port = std::stoi(argv[1]);

    Calcuate calcuate;                                                                // OSI中的应用层
    CallServe callsv(std::bind(&Calcuate::Excute, &calcuate, std::placeholders::_1)); // OSI中的表示层
    io_server server = std::bind(&CallServe::server, &callsv, std::placeholders::_1, std::placeholders::_2);

    std::unique_ptr<TcpServer> tcpsvr = std::make_unique<TcpServer>(port, server); // 会话层
    tcpsvr->Loop();
}